#include "samplers.fx"
#include "shading.fx"

struct VS_IN
{
	float3	position	:	POSITION;
	float3	normal		:	NORMAL;
	float3	tangent		:	TANGENT;
	float2	tex			:	TEX_COORDS;
};
//____________
struct ControlPoint
{
	float3	position	:	POSITION;
};
//____________
struct triTessFactors
{
	float	edge[3]		:	SV_TessFactor;
	float	inside[1]	:	SV_InsideTessFactor;
};
//____________
struct DS_OUT
{
	float4	position	:	SV_POSITION;
	float3	normal		:	NORMAL;
	float2	uv			:	COORDS;
};

//________ V A R I A B L E S____________________________________________________________________________

float4x4	m_World;
float4x4	m_WorldViewProj;
float		fInsideTess;
float		fEdgeTess;
float		fRadius;
float3		vPos;
uint		iTessFactor;
Texture2D	texSpaceship;


//________ S H A D E R S________________________________________________________________________________


ControlPoint VS_Sphere(VS_IN vin)
{
	ControlPoint vout;

	vout.position = vin.position + vPos;
	return vout;
}
//_______________
											// ctrl points per patch
triTessFactors ConstantHS_Sphere(InputPatch<ControlPoint, 3> patch, uint patchID : SV_PrimitiveID) // Constant Hull Shader
{
	triTessFactors tout;

	tout.edge[0] = fEdgeTess;
	tout.edge[1] = fEdgeTess;
	tout.edge[2] = fEdgeTess;
	
	tout.inside[0] = fInsideTess;

	return tout;
}
//_______________

[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("ConstantHS_Sphere")]
[maxtessfactor(64.0f)]
ControlPoint ControlPointHS_Sphere(InputPatch<ControlPoint, 3> ctrlPoints,	uint ctrlPoint_index : SV_OutputControlPointID, 
																			uint patchId		 : SV_PrimitiveID)
{
	return ctrlPoints[ctrlPoint_index];
}
//_______________



[domain("tri")]
DS_OUT	DS_Sphere(triTessFactors tessFactors,	float3 barCoords : SV_DomainLocation, 
												const OutputPatch<ControlPoint, 3> ctrlPoints)
{
	DS_OUT dout;

	float3 pos =	barCoords.x * ctrlPoints[0].position + 
					barCoords.y * ctrlPoints[1].position + 
					barCoords.z * ctrlPoints[2].position;


	float2 uv[3] = { float2(0,0), float2(1,0), float2(0,1) };

	float2 coords = barCoords.x * uv[0] + 
					barCoords.y * uv[1] + 
					barCoords.z * uv[2];


	float3 normal = normalize(pos-vPos);

	pos = normalize(pos-vPos) * fRadius + vPos;

	dout.position = mul(float4(pos,1.0f), m_WorldViewProj);
	dout.normal = normal;

	dout.uv = coords;


	return dout;
}

//_______________


float4 PS_Sphere(DS_OUT pin) : SV_TARGET
{
	float3 color = texSpaceship.Sample(s_linear, pin.uv).xyz;
	
	color *= shade(pin.normal);
	return float4(color,1);

}


//###################################################################################


DS_OUT VS_NoTess(VS_IN vin)
{
	DS_OUT dout = (DS_OUT)0;
	dout.position = mul(float4(vin.position, 1.0f), m_WorldViewProj);
	return dout;

}

float4 PS_NoTess(DS_OUT pin) : SV_TARGET
{
	return float4(1,0,0,1);
}

//###################################################################################


RasterizerState rs_Wireframe
{
	CullMode = Back;
	FillMode = Wireframe;
};


technique11 TessSphere
{
	pass P0
	{
		SetVertexShader( CompileShader( vs_5_0,  VS_Sphere()   ) );
		SetHullShader ( CompileShader ( hs_5_0, ControlPointHS_Sphere() ) );
		SetDomainShader( CompileShader ( ds_5_0, DS_Sphere() ) );
		SetGeometryShader ( NULL );
		SetPixelShader( CompileShader( ps_5_0,   PS_Sphere()   ) );
	}
}


technique11 NoTess
{
	pass P0
	{
		SetVertexShader( CompileShader( vs_5_0,  VS_NoTess()   ) );
		SetPixelShader( CompileShader( ps_5_0,   PS_NoTess()   ) );
		SetRasterizerState(rs_Wireframe);
	}


}